package com.hmall.search.serviceXinYing.impl;

import com.alibaba.fastjson.JSON;
import com.hmall.common.dto.Item;
import com.hmall.common.dto.PageDTO;
import com.hmall.search.pojo.ItemDoc;
import com.hmall.search.pojo.RequestParam;
import com.hmall.search.serviceXinYing.SearchService;
import org.elasticsearch.action.delete.DeleteRequest;
import org.elasticsearch.action.index.IndexRequest;
import org.elasticsearch.action.search.SearchRequest;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.common.xcontent.XContentType;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.SearchHit;
import org.elasticsearch.search.SearchHits;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightBuilder;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightField;
import org.elasticsearch.search.sort.SortOrder;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;


import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

@Service
public class SearchServiceImpl implements SearchService {

    @Autowired
    RestHighLevelClient client;

    //基本搜索功能
    @Override
    public PageDTO<ItemDoc> getSearchPege(RequestParam param) {
        try {

            SearchRequest request = new SearchRequest("item");

            //分类、品牌、价格过滤
            buildBasicQuery(param, request);

            //排序
            if ("price".equals(param.getSortBy())) {
                request.source().sort("price", SortOrder.ASC);
            }


            Integer page = param.getPage();
            Integer size = param.getSize();
            //分页
            request.source().from((page - 1) * size).size(size);

            //高亮
            request.source().highlighter(new HighlightBuilder()
                    .field("name")
                    .requireFieldMatch(false));

            SearchResponse response = client.search(request, RequestOptions.DEFAULT);
            return handleResponse(response);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

    //分类、品牌、价格过滤
    private void buildBasicQuery(RequestParam param, SearchRequest request) {
        BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();

        String key = param.getKey();
        if (key == null || "".equals(key)) {
            boolQueryBuilder.must(QueryBuilders.matchAllQuery());
        } else {
            boolQueryBuilder.must(QueryBuilders.matchQuery("all", key));
        }
        //分类
        if (param.getCategory() != null && !param.getCategory().equals("")) {
            boolQueryBuilder.filter(QueryBuilders.termQuery("category", param.getCategory()));
        }
        //品牌
        if (param.getBrand() != null && !param.getBrand().equals("")) {
            boolQueryBuilder.filter(QueryBuilders.termQuery("brand", param.getBrand()));
        }
        //价格
        if (param.getMinPrice() != null && param.getMaxPrice() != null) {
            boolQueryBuilder.filter(QueryBuilders
                    .rangeQuery("price")
                    .gte(param.getMinPrice() * 100)
                    .lte(param.getMaxPrice() * 100)
            );
        }
        request.source().query(boolQueryBuilder);
    }

    private PageDTO<ItemDoc> handleResponse(SearchResponse response) {

        SearchHits searchHits = response.getHits();
        long total = searchHits.getTotalHits().value;
        SearchHit[] hits = searchHits.getHits();

        List<ItemDoc> hotels = new ArrayList<>();
        for (SearchHit hit : hits) {
            String json = hit.getSourceAsString();
            ItemDoc itemDoc = JSON.parseObject(json, ItemDoc.class);

            //获取高亮
            Map<String, HighlightField> highlightFields = hit.getHighlightFields();
            if (!CollectionUtils.isEmpty(highlightFields)) {
                HighlightField name = highlightFields.get("name");
                if (name != null) {
                    String s = name.getFragments()[0].toString();
                    itemDoc.setName(s);
                }
            }
            itemDoc.setPrice(itemDoc.getPrice());
            hotels.add(itemDoc);
        }
        return new PageDTO<>(total, hotels);
    }


    @RabbitListener(queues = "syn.queue")
    public void listen(String s) throws IOException {
        ItemDoc itemDoc = new ItemDoc();
        Item item = JSON.parseObject(s, Item.class);
        BeanUtils.copyProperties(item,itemDoc);

        if(itemDoc.getId()==1){
            //上架
            String s1 = JSON.toJSONString(itemDoc);
            IndexRequest item1 = new IndexRequest("item").id(itemDoc.getId().toString());

            item1.source(s1, XContentType.JSON);
            client.index(item1,RequestOptions.DEFAULT);
        }if(itemDoc.getId()==2) {
            //下架
            DeleteRequest item1 = new DeleteRequest("item").id(itemDoc.getId().toString());
            client.delete(item1,RequestOptions.DEFAULT);

        }
    }

}
